package edu.luc.cs413s13.team1.monsterm.controller;

import java.util.Random;

import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Point;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
import android.util.Log;

import edu.luc.cs413s13.team1.monsterm.model.DefaultMonstermModel;
import edu.luc.cs413s13.team1.monsterm.model.MonstermModel;
import edu.luc.cs413s13.team1.monsterm.model.cell.Cell;
import edu.luc.cs413s13.team1.monsterm.model.cell.CellEvent;
import edu.luc.cs413s13.team1.monsterm.model.cell.MonstermCell;
import edu.luc.cs413s13.team1.monsterm.model.common.Constants;
import edu.luc.cs413s13.team1.monsterm.model.common.LevelChangeListener;
import edu.luc.cs413s13.team1.monsterm.model.common.ModelChangeListener;
import edu.luc.cs413s13.team1.monsterm.model.monster.Actor;
import edu.luc.cs413s13.team1.monsterm.model.monster.Monster;
import edu.luc.cs413s13.team1.monsterm.view.DefaultMonstermView;

/**
 * The main controller class
 * Receives events from model; manipulates model
 * Receives events from view; invalidates view
 *
 */
public class MonstermController extends Activity implements ModelChangeListener, 
															ViewChangeListener,
															LevelChangeListener {
	
	private DefaultMonstermView view;
	private MonstermModel model;
	UIUpdateThread uiUpdater;
	private int gridWidth;
	private int gridHeight;
	
	// TODO implement the onSaveState
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	    setContentView(R.layout.activity_main);
		view = (DefaultMonstermView) findViewById(R.id.monsterm_view);
	
		// Get display dimensions and derive grid width&height
		final Point displayDimensions = new Point();
		getWindowManager().getDefaultDisplay().getSize(displayDimensions);
		gridWidth = displayDimensions.x / Constants.CELL_SIZE;
		gridHeight = (displayDimensions.y - Constants.VIEW_HEIGHT_MINUS) / Constants.CELL_SIZE;
		Cell[][] cells = new MonstermCell[gridWidth][gridHeight];
		// create cells according to display dimensions
	    for (int i = 0; i < gridWidth; i ++) {
	      for (int j = 0; j < gridHeight; j ++) {
	        cells[i][j] = new MonstermCell(1, this);
	      }
	    }

	    // Initialize the model
		model = new DefaultMonstermModel(cells, this);
		
	    // create actors and populate world in the model
		Random random = new Random(System.currentTimeMillis());
		for (int i = 0; i < Constants.MONSTER_COUNT; i++) {
			int x = random.nextInt(gridWidth);
			int y = random.nextInt(gridHeight);
			Actor monster = new Monster();
			((Monster)monster).setMonsterStateChangeListener(this);
			model.addLivingActor(monster);
		    model.addActor(monster, y, x);
			Log.i(Constants.TAG, "Monster created: " + monster);
		}
		
		// Dependency injection on model
		model.setModelChangeListener(this);
		model.setLevelChangeListener(this);
		//model.setMonsterStateChangeListener(this);

		// Dependency injection on view
		view.setModel(model);
		view.setOnTouchListener(this);
		
		view.init(cells, Constants.CELL_SIZE);
	    
	    // start the initial actors
	    for (Actor a : model.getLivingActors()) {
	    	a.start();
	    }
				
		// Start the UI Update Thread
		uiUpdater = new UIUpdateThread(view);
		(new Thread(uiUpdater)).start();
		
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		//getMenuInflater().inflate(R.menu.activity_main, menu);
		
		return true;
	}
	
	public void exitProgram(MenuItem item) {
		finish();
	}
	
	@Override
	protected void onSaveInstanceState(Bundle savedInstanceState) {
		super.onSaveInstanceState(savedInstanceState);
		//savedInstanceState.putParcelable("model", (Parcelable) model);
		//savedInstanceState.putSerializable("view", (Serializable) view);
	}
	
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);
		//model = (MonstermModel)savedInstanceState.get("model");
		//view = (DefaultMonstermView)savedInstanceState.get("view");
		//updateView();
		//view.invalidate();
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		Log.d(Constants.TAG, "Touch event caught!");
		Cell[][] grid = model.getWorld().getGrid();
		
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			int x = (int)event.getX();
			int y = (int)event.getY();
			int gridX = x / Constants.CELL_SIZE;
			int gridY = y / Constants.CELL_SIZE;
			if (gridX >= gridWidth || gridY >= gridHeight) {
				return false;
			}
			Cell cell = grid[gridX][gridY];
			int count = cell.getOccupants().size();
			if (count > 0) {
				Monster monster = (Monster)cell.getOccupants().get(0);
				if (!monster.isProtected()) {
					if (monster.kill()) {
						model.updateScore(1); // Add 1 to current score
						model.removeLivingActor(monster);
						return true;
					}
				}
			}
			//Log.i(Constants.TAG, "You clicked on pixel: (" + x + ", "+ y +")");
			//Log.i(Constants.TAG, "You clicked on cell: (" + gridX + ", " + gridY +")");
			//Log.i(Constants.TAG, "Grid dimensions: (" + grid.length + ", " + grid[0].length+")");
			
		}
		
		return false;
	}

	// TODO The next couple of methods are kept for future enhancement
	//		they will help to eliminate UIUpdateThread 
	@Override
	public void onMonsterStateChange(int stateId) {
		//view.invalidate();
		//Log.i(Constants.TAG, "Controller: monster state: " + stateId);
	}

	@Override
	public void onModelChange() {
		//view.invalidate();
	}

	@Override
	public void onEnterCell(CellEvent event) {
		//Log.d(Constants.TAG, "Controller: on enter cell!");
		//view.invalidate();
	}

	@Override
	public void onLeaveCell(CellEvent event) {
		//view.invalidate();
	}
	 
	private void showToast(String msg, int length) {
		Toast.makeText(getApplicationContext(), msg, length).show();
	}

	@Override
	public void onLevelChange(int level) {
		if (level <= 2) {
			String msg = "Transitioning to level "+model.getCurrentLevel();
			showToast(msg, Toast.LENGTH_SHORT);
		} else if (level >= 3 ) {
			exitMonsterm("Game over! Your score: " + model.getScore());
			//showToast("Game over! Your score: ", model.getScore());
		}		
	}
	
	/**
	 * Finalizing the app; do clean up, etc.
	 * 
	 * @param msg The message to be displayed upon exit
	 */
	private void exitMonsterm(String msg) {
		model.exitMonsterm();
		uiUpdater.done();
		
		AlertDialog.Builder alert = new AlertDialog.Builder(this);
		// set title
		alert.setTitle("MonsTerm");
 		// set dialog message
		alert
			.setMessage(msg)
			.setCancelable(false)
			.setPositiveButton("Exit Game",new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog,int id) {
					MonstermController.this.finish();
					System.exit(0);
				}
			});
		// create alert dialog
		AlertDialog alertDialog = alert.create();
		// show it
		alertDialog.show();
		
		view.invalidate();
		
	}
}
